import Color, { HSLColor } from './Color';
import Utils from '../Utils';

export abstract class ColorPattern {
  protected readonly seedColor: Color;

  protected constructor(seedColor: Color) {
    this.seedColor = seedColor;
  }

  static fromSeekColor(seekColor: Color): {
    light: LightColorPattern;
    dark: DarkColorPattern;
  } {
    return {
      light: new LightColorPattern(seekColor),
      dark: new DarkColorPattern(seekColor),
    };
  }

  abstract get primary(): Color;

  abstract get onPrimary(): Color;

  abstract get background(): Color;

  abstract get onBackground(): Color;

  abstract get divider(): Color;
}

export class LightColorPattern extends ColorPattern {
  private  readonly hslSeedColor: HSLColor;
  private readonly luminance: number;

  constructor(seedColor: Color) {
    super(seedColor);
    this.hslSeedColor = seedColor.toHSL();
    this.luminance = seedColor.luminance;
  }

  get primary(): Color {
    return this.seedColor;
  }

  get onPrimary(): Color {
    if (this.luminance > 0.5) {
      return this.hslSeedColor.copyWith({
        s: 0.1, l: 0
      }).toRGB();
    } else {
      return this.hslSeedColor.copyWith({
        s: 0.1, l: 1
      }).toRGB();
    }
  }

  get background(): Color {
    return this.hslSeedColor.copyWith({
      s: 0.1, l: 0.95
    }).toRGB();
  }

  get onBackground(): Color {
    return this.hslSeedColor.copyWith({
      s: 0.1, l: 0.05
    }).toRGB();
  }

  get divider(): Color {
    return this.onBackground.withOpacity(0.2);
  }
}

export class DarkColorPattern extends ColorPattern {
  private  readonly hslSeedColor: HSLColor;
  private readonly luminance: number;

  constructor(seedColor: Color) {
    let hslSeedColor = seedColor.toHSL()
    hslSeedColor = hslSeedColor.copyWith({
      s: Utils.clamp(hslSeedColor.saturation - 0.2, {
        min: 0.1, max: 0.9
      })
    });
    seedColor = hslSeedColor.toRGB();
    super(seedColor);
    this.hslSeedColor = hslSeedColor;
    this.luminance = seedColor.luminance;
  }

  get primary(): Color {
    return this.seedColor;
  }

  get onPrimary(): Color {
    if (this.luminance > 0.5) {
      return this.hslSeedColor.copyWith({
        s: 0.1, l: 0
      }).toRGB().withOpacity(0.9);
    } else {
      return this.hslSeedColor.copyWith({
        s: 0.1, l: 1
      }).toRGB().withOpacity(0.7);
    }
  }

  get background(): Color {
    return this.hslSeedColor.copyWith({
      s: 0.1, l: 0.05
    }).toRGB();
  }

  get onBackground(): Color {
    return this.hslSeedColor.copyWith({
      s: 0.1, l: 0.95
    }).toRGB().withOpacity(0.9);
  }

  get divider(): Color {
    return this.onBackground.withOpacity(0.2);
  }
}